package com.dg.lecheng.manager.shiro;

import com.dg.lecheng.api.user.model.InfoUser;
import com.dg.lecheng.api.user.service.InfoUserAuthService;
import com.dg.lecheng.api.user.service.InfoUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 提供了访问控制的基础功能
 * Created by jn-dinggao on 2017/11/9.
 */
public class SysUserAccessFilter extends AccessControlFilter {

    @Autowired
    private InfoUserService infoUserService;
    @Autowired
    private InfoUserAuthService infoUserAuthService;


    /**
     * 表示是否允许访问；mappedValue就是[urls]配置中拦截器参数部分，如果允许访问返回true，否则false；
     * @param servletRequest
     * @param servletResponse
     * @param o
     * @return
     * @throws Exception
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {

        String loginName = (String)SecurityUtils.getSubject().getPrincipal();
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String contentPath = request.getContextPath();
        String uri = request.getRequestURI();
        uri = uri.replaceAll(contentPath,"");
        System.err.println("uri : " + uri);
        if("/".equals(uri)){
            return true;
        }
        if(StringUtils.isEmpty(loginName)){
            return false;
        }
        InfoUser infoUser = infoUserService.getByUserName(loginName);
        if(infoUser == null){
            return false;
        }

        List<Map> auths = infoUserAuthService.getUserAuth(infoUser.getId());
        if(!isContainAuth(auths,uri)){
            return false;
        }

        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

        Subject subject = getSubject(servletRequest, servletResponse);
        if (subject.getPrincipal() == null) {//表示没有登录，重定向到登录页面
            saveRequest(servletRequest);
            WebUtils.toHttp(servletResponse).sendError(1101);
        } else {
            //否则返回1001:没有权限 自定义未授权状态码
             WebUtils.toHttp(servletResponse).sendError(1001);

        }


        return false;
    }

    /**
     * 用户资源列表中是否包含访问路径
     * @param auths
     * @param uri
     * @return
     */
    public boolean isContainAuth(List<Map> auths ,String uri){
        boolean isContainAuth = false;
        for(Map map : auths){
            if(uri.equals(map.get("uri").toString()) || matching(uri,map.get("uri").toString())){
                isContainAuth = true;
                return isContainAuth;
            }
        }
        return isContainAuth;
    }

    /**
     * 正则表达式匹配  解决这种 /getRoleByUserId/123
     * @param ori
     * @param regex
     * @return
     */
    public boolean matching(String ori,String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(ori);
        return matcher.matches();
    }

    public static void main(String[] args) {
        String a = "/infoAuth/get/[0-9]* ";
        String b = "/infoAuth/get/42";
        System.out.println(new SysUserAccessFilter().matching(b,a));
    }
}
